package com.sqx.modules.pay.controller;


import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.sqx.common.utils.PageUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.entity.UserMoneyDetails;
import com.sqx.modules.app.response.UserMessageResponse;
import com.sqx.modules.app.service.UserMoneyDetailsService;
import com.sqx.modules.app.service.UserMoneyService;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.message.entity.MessageInfo;
import com.sqx.modules.message.service.MessageService;
import com.sqx.modules.pay.config.AliPayConstants;
import com.sqx.modules.pay.entity.AliPayWithdrawModel;
import com.sqx.modules.pay.entity.CashOut;
import com.sqx.modules.pay.service.CashOutService;
import com.sqx.modules.pay.service.PayDetailsService;
import com.sqx.modules.utils.EasyPoi.ExcelUtils;
import com.sqx.modules.utils.wx.*;
import com.sqx.modules.utils.AmountCalUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.transferbatch.TransferBatchService;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author fang
 * @date 2020/5/15
 */
@Slf4j
@RestController
@Api(value = "管理平台", tags = {"管理平台"})
@RequestMapping(value = "/cash")
public class CashController {

    /**
     * 充值记录
     */
    @Autowired
    private PayDetailsService payDetailsService;
    /**
     * 提现记录
     */
    @Autowired
    private CashOutService cashOutService;
    /**
     * app用户
     */
    @Autowired
    private UserService userService;
    /**
     * 通用配置
     */
    @Autowired
    private CommonInfoService commonInfoService;
    @Autowired
    private UserMoneyDetailsService userMoneyDetailsService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private UserMoneyService userMoneyService;
    public static TransferBatchService service;
    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(true);

    @RequestMapping(value = "/sendMsgByUserId", method = RequestMethod.GET)
    @ApiOperation("管理平台主动推送消息(指定用户)")
    @ResponseBody
    public Result sendMsgByUserId(@ApiParam("标题")String title,
                                  @ApiParam("内容")String content,
                                  @ApiParam("用户id")Long userId) {
        UserEntity user = userService.queryByUserId(userId);
        send(user, title, content);
        return Result.success();
    }


    @RequestMapping(value = "/sendMsg", method = RequestMethod.GET)
    @ApiOperation("管理平台主动推送消息")
    @ResponseBody
    public Result sendMsg(@ApiParam("标题")String title,
                          @ApiParam("内容")String content,
                          @ApiParam("电话")String phone,
                          @ApiParam("1手机号推送 2所有人推送")Integer flag) {
        if (flag == 1) {
            //根据手机号推送
            UserEntity userByPhone = userService.queryByPhone(phone);
            if (null == userByPhone) {
                return Result.error(-100, "手机号不存在！");
            }
            send(userByPhone, title, content);
        } else {
            //所有人推送
            List<UserEntity> userInfos = userService.list();
            //用户数量较大  使用多线程推送  根据用户数量进行拆分  同时按照3个线程进行推送
            int count = userInfos.size() / 3;
            new Thread(() -> {
                for (int i = 0; i < count; i++) {
                    send(userInfos.get(i), title, content);
                }
            }).start();
            new Thread(() -> {
                for (int i = count; i < count * 2; i++) {
                    send(userInfos.get(i), title, content);
                }
            }).start();
            new Thread(() -> {
                for (int i = count * 2; i < userInfos.size(); i++) {
                    send(userInfos.get(i), title, content);
                }
            }).start();
           /* for(UserInfo userByPhone:userInfos){

            }*/
        }
        return Result.success();
    }

    private void send(UserEntity userByPhone, String title, String content) {
        if (userByPhone.getClientid() != null) {
            userService.pushToSingle(title, content, userByPhone.getClientid());
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        MessageInfo messageInfo = new MessageInfo();
        messageInfo.setContent(content);
        messageInfo.setTitle(title);
        messageInfo.setState(String.valueOf(6));
        messageInfo.setUserName(userByPhone.getUserName());
        messageInfo.setUserId(String.valueOf(userByPhone.getUserId()));
        messageInfo.setCreateAt(simpleDateFormat.format(new Date()));
        messageInfo.setIsSee("0");
        messageService.saveBody(messageInfo);
    }


    @RequestMapping(value = "/selectCashOut", method = RequestMethod.GET)
    @ApiOperation("获取最新的提现信息")
    @ResponseBody
    public Result selectCashOut() {
        return Result.success().put("data", cashOutService.selectCashOutLimit3());
    }

    @RequestMapping(value = "/selectSumPay", method = RequestMethod.GET)
    @ApiOperation("查询用户充值金额")
    @ResponseBody
    public Result selectSumPay(@ApiParam("开始时间") String createTime,@ApiParam("结束时间") String endTime,
                               @ApiParam("用户id") Long userId) {
        return Result.success().put("data", payDetailsService.selectSumPay(createTime, endTime, userId));
    }

    @RequestMapping(value = "/selectUserRecharge", method = RequestMethod.GET)
    @ApiOperation("查询所有用户充值信息列表")
    @ResponseBody
    public Result selectUserRecharge(@ApiParam("页码")int page,
                                     @ApiParam("条数")int limit,
                                     @ApiParam("开始时间")String startTime,
                                     @ApiParam("结束时间")String endTime,
                                     @ApiParam("0待支付 1支付成功 2失败")Integer state,
                                     @ApiParam("手机号")String phone,
                                     @ApiParam("用户名")String userName,
                                     @ApiParam("订单号")String orderId,
                                     @ApiParam("支付方式")Integer classify) {
        return Result.success().put("data", payDetailsService.selectPayDetails(page, limit, startTime, endTime, null, state,phone,userName,orderId,classify));
    }

    @RequestMapping(value = "/selectUserRechargeByUserId", method = RequestMethod.GET)
    @ApiOperation("查询某个用户充值信息列表")
    @ResponseBody
    public Result selectUserRechargeByUserId(@ApiParam("页码")int page,
                                             @ApiParam("条数")int limit,
                                             @ApiParam("开始时间")String startTime,
                                             @ApiParam("结束时间")String endTime,
                                             @ApiParam("用户id")Long userId,
                                             @ApiParam("0待支付 1支付成功 2失败")Integer state) {
        return Result.success().put("data", payDetailsService.selectPayDetails(page, limit, startTime, endTime, userId, state,null,null,null,null));
    }

    @RequestMapping(value = "/selectUserRechargeByUserIdApp", method = RequestMethod.GET)
    @ApiOperation("查询某个用户充值信息列表")
    @ResponseBody
    public Result selectUserRechargeByUserIdApp(@ApiParam("页码")int page,
                                                @ApiParam("条数")int limit,
                                                @ApiParam("开始时间")String startTime,
                                                @ApiParam("结束时间")String endTime,
                                                @ApiParam("用户id")Long userId) {
        return Result.success().put("data", payDetailsService.selectPayDetails(page, limit, startTime, endTime, userId, 1,null,null,null,null));
    }

    @RequestMapping(value = "/selectPayDetails", method = RequestMethod.GET)
    @ApiOperation("查询提现记录列表")
    @ResponseBody
    public Result selectHelpProfit(@ApiParam("页码")int page,
                                   @ApiParam("条数")int limit,
                                   @ApiParam("支付宝名称")String zhifubaoName,
                                   @ApiParam("支付宝账号")String zhifubao,
                                   @ApiParam("用户id")String userId,
                                   @ApiParam("提现方式 1支付宝 2微信小程序  3微信公众号")Integer classify,
                                   @ApiParam("状态 0待转账 1成功 -1退款")Integer state) {
        Map<String, Object> map = new HashMap<>();
        map.put("page", page);
        map.put("limit", limit);
        map.put("zhifubaoName", zhifubaoName);
        map.put("zhifubao", zhifubao);
        map.put("userId", userId);
        map.put("classify", classify);
        map.put("state", state);
        PageUtils pageUtils = cashOutService.selectCashOutList(map);
        return Result.success().put("data", pageUtils);
    }


    @ApiOperation("财务提现统计")
    @GetMapping("/statisticsCashMoney")
    public Result statisticsMoney(@ApiParam("时间（年月日）")String time,
                                  @ApiParam("筛选1 按年月日 2年月 3年")Integer flag) {
        // 累计提现金额(所有的)
        Double sumMoney = cashOutService.sumMoney(time, flag);
        // 累计提现笔数(所有的)
        Integer countMoney = cashOutService.countMoney(time, flag);
        // 待转账次数
        Integer stayMoney = cashOutService.stayMoney(time, flag);
        // 待提现金额
        BigDecimal daiTXMoney = cashOutService.daiTXMoney(time, flag);
        // 累计已提现金额（成功的）
        BigDecimal yiTXMoney = cashOutService.yiTXMoney(time, flag);
        // 累计提现次数(成功的)
        Integer yiTXCount = cashOutService.yiTXCount(time, flag);
        // 微信总提现次数
        Integer weiXinXCXMoney = cashOutService.weiXinXCXMoney(time, flag);
        // 支付宝总提现次数
        Integer zfbMoneyCount = cashOutService.zfbMoneyCount(time, flag);
        // 微信已提现金额
        BigDecimal weiXinMoney = cashOutService.weiXinMoney(time, flag);
        // 支付宝已提现金额
        BigDecimal zfbMoney = cashOutService.zfbMoney(time, flag);
        // 申请提现金额
        BigDecimal applyMoney = cashOutService.daiTXMoney(time, flag);
        // 拒绝提现金额
        BigDecimal refuseMoney = cashOutService.refuseMoney(time, flag);
        // 拒绝提现笔数
        Integer refuseMoneyCount = cashOutService.refuseMoneyCount(time, flag);


        Map<String, Object> map = new HashMap<>();
        map.put("sumMoney", sumMoney == null ? 0.00 : sumMoney);
        map.put("countMoney", countMoney == null ? 0 : countMoney);
        map.put("stayMoney", stayMoney == null ? 0 : stayMoney);
        map.put("daiTXMoney", daiTXMoney == null ? 0.00 : daiTXMoney);
        map.put("yiTXMoney", yiTXMoney == null ? 0.00 : yiTXMoney);
        map.put("yiTXCount", yiTXCount == null ? 0 : yiTXCount);
        map.put("weiXinXCXMoney", weiXinXCXMoney == null ? 0 : weiXinXCXMoney);
        map.put("weiXinMoney", weiXinMoney == null ? 0.00 : weiXinMoney);
        map.put("zfbMoney", zfbMoney == null ? 0.00 : zfbMoney);
        map.put("applyMoney", applyMoney == null ? 0.00 : applyMoney);
        map.put("refuseMoney", refuseMoney == null ? 0.00 : refuseMoney);
        map.put("zfbMoneyCount", zfbMoneyCount == null ? 0 : zfbMoneyCount);
        map.put("refuseMoneyCount", refuseMoneyCount == null ? 0 : refuseMoneyCount);
        return Result.success().put("data", map);
    }


    @ApiOperation("充值统计")
    @GetMapping("/payMember")
    public Result payMember(@ApiParam("时间（年月日）")String time,
                            @ApiParam("筛选1 按年月日 2年月 3年")Integer flag,
                            @ApiParam("支付方式 1支付宝 2微信公众号  3微信小程序")Integer payClassify) {
        Double sumMoney = payDetailsService.selectSumPayByClassify(time, flag, null, payClassify);
        Double weiXinGZHMoney = payDetailsService.selectSumPayByClassify(time, flag, 2, payClassify);
        Double weiXinXCXMoney = payDetailsService.selectSumPayByClassify(time, flag, 3, payClassify);
        Map<String, Object> map = new HashMap<>();
        map.put("sumMoney", sumMoney == null ? 0.00 : sumMoney);
        map.put("weiXinGZHMoney", weiXinGZHMoney == null ? 0.00 : weiXinGZHMoney);
        map.put("weiXinXCXMoney", weiXinXCXMoney == null ? 0.00 : weiXinXCXMoney);
        return Result.success().put("data", map);
    }


    @RequestMapping(value = "/alipay", method = RequestMethod.POST)
    @ApiOperation("管理平台确认提现")
    @ResponseBody
    public Result alipayPay(@ApiParam("提现id") Long cashId) {
        reentrantReadWriteLock.writeLock().lock();
        try {
            CashOut one = cashOutService.selectById(cashId);
            if (one.getClassify() == null || one.getClassify() == 1) {
                return cashAliPay(one);
            } else {
                return cashWxPay(one);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("转账异常" + e.getMessage());
        } finally {
            reentrantReadWriteLock.writeLock().unlock();
        }
        return Result.error("系统繁忙，请稍后再试！");
    }


    public Result cashAliPay(CashOut one) {
        //提现订单
        log.error("进来了！！！");
        //订单记录不为空
        if (one == null) {
            return Result.error("提现记录不存在！");
        }
        //订单状态不是待转帐
        if (one.getState() != 0) {
            return Result.error(9999, one.getZhifubaoName() + "转账失败！原因是用户已转账");
        }
        //订单编号为空
        if (StringUtils.isEmpty(one.getOrderNumber())) {
            one.setOrderNumber(String.valueOf(System.currentTimeMillis()));
        }
        //配置文件对象
        CommonInfo commonInfo = commonInfoService.findOne(98);

        CommonInfo name = commonInfoService.findOne(12);
        if (commonInfo.getValue() != null && commonInfo.getValue().equals("1")) {

            try {
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");  //gateway:支付宝网关（固定）https://openapi.alipay.com/gateway.do
                certAlipayRequest.setAppId(commonInfoService.findOne(63).getValue());  //APPID 即创建应用后生成,详情见创建应用并获取 APPID
                certAlipayRequest.setPrivateKey(commonInfoService.findOne(65).getValue());  //开发者应用私钥，由开发者自己生成
                certAlipayRequest.setFormat("json");  //参数返回格式，只支持 json 格式
                certAlipayRequest.setCharset(AliPayConstants.CHARSET);  //请求和签名使用的字符编码格式，支持 GBK和 UTF-8
                certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);  //商户生成签名字符串所使用的签名算法类型，目前支持 RSA2 和 RSA，推荐商家使用 RSA2。
                CommonInfo url = commonInfoService.findOne(200);
                certAlipayRequest.setCertPath(url.getValue() + "/appCertPublicKey.crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                certAlipayRequest.setAlipayPublicCertPath(url.getValue() + "/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                certAlipayRequest.setRootCertPath(url.getValue() + "/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
                AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
                request.setBizContent("{" +
                        "\"out_biz_no\":\"" + one.getOrderNumber() + "\"," +             //订单编号
                        "\"trans_amount\":" + new BigDecimal(one.getMoney()) + "," +     //转账金额
                        "\"product_code\":\"TRANS_ACCOUNT_NO_PWD\"," +
                        "\"biz_scene\":\"DIRECT_TRANSFER\"," +
                        "\"order_title\":\"" + name.getValue() + "佣金结算" + "\"," +
                        "\"payee_info\":{" +
                        "\"identity\":\"" + one.getZhifubao() + "\"," +                  //支付宝账号
                        "\"identity_type\":\"ALIPAY_LOGON_ID\"," +
                        "\"name\":\"" + one.getZhifubaoName() + "\"," +                  //支付宝名称
                        "}," +
                        "\"remark\":\"" + name.getValue() + "佣金结算" + "\"" +
                        "}");
                AlipayFundTransUniTransferResponse response = null;
                response = alipayClient.certificateExecute(request);
                log.error("支付宝转账返回值：" + response.getBody());
                //如果转账成功
                if (AliPayConstants.SUCCESS_CODE.equalsIgnoreCase(response.getCode())) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    //修改状态为转账成功
                    one.setState(1);
                    //设置转账时间
                    one.setOutAt(sdf.format(new Date()));
                    //更新转账订单
                    cashOutService.update(one);
                    //查询用户
                    UserEntity userInfo = userService.queryByUserId(one.getUserId());
                    cashOutService.cashOutSuccess(userInfo, one.getOutAt(), one.getMoney(), one.getZhifubao(), commonInfoService.findOne(19).getValue());

                    return Result.success(one.getZhifubaoName() + "转账成功");
                } else {
                    return Result.error(9999, one.getZhifubaoName() + "转账失败！" + response.getSubMsg());
                }
            } catch (AlipayApiException e) {
                log.error("零钱提现异常原因:" + e.getMessage());
                e.printStackTrace();
                return Result.error(9999, one.getZhifubaoName() + "转账失败！" + e.getMessage());
            }
        } else if (commonInfo.getValue() != null && commonInfo.getValue().equals("2")) {
            AlipayClient alipayClient = new DefaultAlipayClient(AliPayConstants.REQUEST_URL,
                    commonInfoService.findOne(63).getValue(), commonInfoService.findOne(65).getValue(), AliPayConstants.FORMAT,
                    AliPayConstants.CHARSET, commonInfoService.findOne(64).getValue(), AliPayConstants.SIGNTYPE);
            val aliPayWithdrawModel = AliPayWithdrawModel.builder()
                    .out_biz_no(one.getOrderNumber())
                    .amount(new BigDecimal(one.getMoney()))
                    .payee_account(one.getZhifubao())
                    .payee_real_name(one.getZhifubaoName())
                    .payee_type(AliPayConstants.PAY_TYPE)
                    .remark(name.getValue())
                    .build();
            String json = JSON.toJSONString(aliPayWithdrawModel);
            //实例化连接对象
            AlipayFundTransToaccountTransferRequest withdrawRequest = new AlipayFundTransToaccountTransferRequest();
            withdrawRequest.setBizContent(json);
            try {
                AlipayFundTransToaccountTransferResponse response = alipayClient.execute(withdrawRequest);
                if (AliPayConstants.SUCCESS_CODE.equalsIgnoreCase(response.getCode())) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    //修改状态为转账成功
                    one.setState(1);
                    //设置转账时间
                    one.setOutAt(sdf.format(new Date()));
                    //更新转账订单
                    cashOutService.update(one);
                    //查询用户
                    UserEntity userInfo = userService.queryByUserId(one.getUserId());
                    cashOutService.cashOutSuccess(userInfo, one.getOutAt(), one.getMoney(), one.getZhifubao(), commonInfoService.findOne(19).getValue());
                    return Result.success(one.getZhifubaoName() + "转账成功");
                } else {
                    return Result.error(9999, one.getZhifubaoName() + "转账失败！" + response.getSubMsg());
                }
            } catch (AlipayApiException e) {
                log.error("零钱提现异常原因:" + e.getMessage());
                e.printStackTrace();
                return Result.error(9999, one.getZhifubaoName() + "转账失败！" + e.getMessage());

            }
        } else {
            //人工转账后改变状态的
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            one.setState(1);
            one.setOutAt(sdf.format(now));
            cashOutService.update(one);
            UserEntity userInfo = userService.queryByUserId(one.getUserId());
            cashOutService.cashOutSuccess(userInfo, one.getOutAt(), one.getMoney(), one.getZhifubao(), commonInfoService.findOne(19).getValue());
            return Result.success(one.getZhifubaoName() + "转账成功");
        }
    }


    private Result cashWxPay(CashOut one) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        UserEntity userEntity = userService.getById(one.getUserId());
        if (StringUtils.isEmpty(one.getOrderNumber())) {
            one.setOrderNumber(String.valueOf(System.currentTimeMillis()));
        }
        String value = commonInfoService.findOne(244).getValue();
        if ("1".equals(value)) {
            double v = Double.parseDouble(one.getMoney());
            Double mul = AmountCalUtils.mul(v, 100);
            Integer amount = mul.intValue();

            /** 商户号 */
            String merchantId = commonInfoService.findOne(76).getValue();
            /** 商户API私钥路径 */
            String privateKeyPath = commonInfoService.findOne(629).getValue();
            /** 商户证书序列号 */
            String merchantSerialNumber = commonInfoService.findOne(630).getValue();
            /** 商户APIV3密钥 */
            String apiV3Key = commonInfoService.findOne(631).getValue();
            Config config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(merchantId)
                    .privateKeyFromPath(privateKeyPath)
                    .merchantSerialNumber(merchantSerialNumber)
                    .apiV3Key(apiV3Key)
                    .build();
            service = new TransferBatchService.Builder().config(config).build();
            InitiateBatchTransferRequest initiateBatchTransferRequest =
                    new InitiateBatchTransferRequest();
            if (one.getClassify() == 2) {
                CommonInfo mchAppId = commonInfoService.findOne(45);
                initiateBatchTransferRequest.setAppid(mchAppId.getValue());
            } else if (one.getClassify() == 3) {
                CommonInfo mchAppId = commonInfoService.findOne(5);
                initiateBatchTransferRequest.setAppid(mchAppId.getValue());
            }
            CommonInfo one1 = commonInfoService.findOne(12);
            //【商家批次单号】 商户系统内部的商家批次单号，要求此参数只能由数字、大小写字母组成，在商户系统内部唯一
            initiateBatchTransferRequest.setOutBatchNo(one.getOrderNumber());
            //【批次名称】 该笔批量转账的名称
            initiateBatchTransferRequest.setBatchName(one1.getValue() + "提现金额到账");
            //【批次备注】 转账说明，UTF8编码，最多允许32个字符
            initiateBatchTransferRequest.setBatchRemark(one1.getValue() + "提现金额到账");
            //【转账总金额】 转账金额单位为“分”。转账总金额必须与批次内所有明细转账金额之和保持一致，否则无法发起转账操作
            initiateBatchTransferRequest.setTotalAmount(amount.longValue());
            //【转账总笔数】 一个转账批次单最多发起一千笔转账。转账总笔数必须与批次内所有明细之和保持一致，否则无法发起转账操作
            initiateBatchTransferRequest.setTotalNum(1);
            {
                //【转账明细列表】 发起批量转账的明细列表，最多一千笔
                List<TransferDetailInput> transferDetailListList = new ArrayList<>();
                {
                    TransferDetailInput transferDetailInput = new TransferDetailInput();
                    //【商家明细单号】 商户系统内部区分转账批次单下不同转账明细单的唯一标识，要求此参数只能由数字、大小写字母组成
                    transferDetailInput.setOutDetailNo(one.getOrderNumber());
                    //【转账金额】 转账金额单位为“分”
                    transferDetailInput.setTransferAmount(amount.longValue());
                    //【转账备注】 单条转账备注（微信用户会收到该备注），UTF8编码，最多允许32个字符
                    transferDetailInput.setTransferRemark(one1.getValue() + "提现金额到账");
                    //【收款用户openid】 商户appid下，某用户的openid

                    if (one.getClassify() == 2) {
                        transferDetailInput.setOpenid(userEntity.getOpenId());
                    } else if (one.getClassify() == 3) {
                        transferDetailInput.setOpenid(userEntity.getWxOpenId());
                    }


                    //【收款用户姓名】 收款方真实姓名。支持标准RSA算法和国密算法，公钥由微信侧提供
                    //明细转账金额<0.3元时，不允许填写收款用户姓名
                    //明细转账金额 >= 2,000元时，该笔明细必须填写收款用户姓名
                    //同一批次转账明细中的姓名字段传入规则需保持一致，也即全部填写、或全部不填写
                    //若商户传入收款用户姓名，微信支付会校验用户openID与姓名是否一致，并提供电子回单
                    //transferDetailInput.setUserName("757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45");
                    transferDetailListList.add(transferDetailInput);
                }
                initiateBatchTransferRequest.setTransferDetailList(
                        transferDetailListList);
            }
            //【转账场景ID】 该批次转账使用的转账场景，如不填写则使用商家的默认场景，如无默认场景可为空，可前往“商家转账到零钱-前往功能”中申请。
            //如：1001-现金营销
            //initiateBatchTransferRequest.setTransferSceneId("1000");
            //【通知地址】 异步接收微信支付结果通知的回调地址，通知url必须为公网可访问的url，必须为https，不能携带参数。
            //initiateBatchTransferRequest.setNotifyUrl("https://www.weixin.qq.com/wxpay/pay.php");
            try {
                InitiateBatchTransferResponse response = service.initiateBatchTransfer(initiateBatchTransferRequest);
                one.setState(1);
                one.setOutAt(sdf.format(new Date()));
                cashOutService.update(one);
                if (userEntity != null && userEntity.getOpenId() != null) {
                    //提现通知消息
                    cashOutService.cashOutSuccess(userEntity, one.getOutAt(), one.getMoney(), one.getZhifubao(), commonInfoService.findOne(19).getValue());
                }
                MessageInfo messageInfo = new MessageInfo();
                messageInfo.setContent(one.getMoney() + "提现已到账");
                messageInfo.setTitle("提现到账");
                messageInfo.setState(String.valueOf(6));
                messageInfo.setUserName(userEntity.getUserName());
                messageInfo.setUserId(String.valueOf(userEntity.getUserId()));
                messageInfo.setCreateAt(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                messageService.saveBody(messageInfo);
                return Result.success(userEntity.getUserName() + "转账成功");
            } catch (Exception e) {
                e.printStackTrace();
                String message = e.getMessage();
                int i = message.indexOf("\"message\":\"");
                int i1 = message.indexOf("\"}]");
                String substring = message.substring(i + 11, i1);
                return Result.error("转账失败！原因：" + substring);
            }
        } else {
            Date now = new Date();
            one.setState(1);
            one.setOutAt(sdf.format(now));
            cashOutService.update(one);
            UserEntity userInfo = userService.queryByUserId(one.getUserId());
            cashOutService.cashOutSuccess(userInfo, one.getOutAt(), one.getMoney(), one.getZhifubao(), commonInfoService.findOne(19).getValue());
            return Result.success(userEntity.getUserName() + "转账成功");
        }

    }


    @RequestMapping(value = "/refund", method = RequestMethod.POST)
    @ApiOperation("管理平台退款")
    @ResponseBody
    public Result refund(@ApiParam("提现id") Long cashId,@ApiParam("原因内容") String content) {
        CashOut one = cashOutService.selectById(cashId);
        if (one == null) {
            return Result.error("提现信息不存在");
        }
        //将状态为待提现的退款
        if (one.getState() != 0) {
            return Result.error(-100, "状态错误，已经转账或退款!");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        //修改提现订单状态
        one.setState(-1);
        one.setRefund(content);
        one.setOutAt(sdf.format(now));
        cashOutService.update(one);
        Long userId = one.getUserId();
        UserEntity userInfo = userService.getById(userId);
        if (userInfo != null) {
            //将金额退还
            BigDecimal cashMoney = BigDecimal.valueOf(one.getRate()).add(new BigDecimal(one.getMoney()));
            UserMoneyDetails userMoneyDetails = new UserMoneyDetails();
            userMoneyDetails.setUserId(userInfo.getUserId());
            userMoneyDetails.setTitle("[退款提醒]退款：" + cashMoney);
            userMoneyDetails.setContent("退款原因：" + content);
            userMoneyDetails.setType(1);
            userMoneyDetails.setClassify(0);
            userMoneyDetails.setMoney(cashMoney);
            userMoneyDetails.setCreateTime(sdf.format(now));
            userMoneyDetailsService.save(userMoneyDetails);
            userInfo.setBalance(userInfo.getBalance().add(cashMoney));
            userService.updateById(userInfo);
            cashOutService.updateMayMoney(1, userId, cashMoney.doubleValue());
            cashOutService.refundSuccess(userInfo, one.getOutAt(), one.getMoney(), commonInfoService.findOne(19).getValue(), content);
        }
        return Result.success();
    }

    @GetMapping(value = "/cashMoney")
    @ApiOperation("发起提现")
    public Result cashMoney(@ApiParam("用户id")Long userId, @ApiParam("金额")BigDecimal money,
                            @ApiParam("提现方式 1支付宝 2微信小程序  3微信公众号") Integer classify) {
        return cashOutService.cashMoney(userId, money, classify);
    }

    @GetMapping("/exportExcel")
    public void cashListExcel(@ApiParam("提现实体")CashOut cashOut,
                              @ApiParam("开始时间")String startTime,
                              @ApiParam("结束时间")String endTime, HttpServletResponse response) throws IOException {
        List<CashOut> list = cashOutService.selectAdminHelpProfit(null, null, startTime, endTime, cashOut).getRecords();
        ExcelUtils.exportExcel(list, "提现统计表", "提现统计Sheet", CashOut.class, "提现统计表", response);
    }

    @RequestMapping(value = "/selectAdminHelpProfit", method = RequestMethod.GET)
    @ApiOperation("管理员查询提现记录列表")
    @ResponseBody
    public Result selectAdminHelpProfit(@ApiParam("页码")Integer page, @ApiParam("条数")Integer limit,
                                        @ApiParam("开始时间")String startTime,
                                        @ApiParam("结束时间")String endTime,
                                        @ApiParam("提现实体")CashOut cashOut) {
        return Result.success().put("data", cashOutService.selectAdminHelpProfit(page, limit, startTime, endTime, cashOut));
    }

}